import 'package:inmotion_pro/service/db_tables/db_tables.dart';
import 'package:inmotion_pro/service/log/log_cache_model.dart';
import 'package:inmotion_pro/service/log/log_level.dart';
import 'package:flutter/foundation.dart';
import 'package:get/get.dart';
import 'package:logging/logging.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

// 日志服务
class LogService extends GetxService {
  // 获取日志服务实例
  static LogService get to => Get.find();

  static const _databaseName = 'app_logs.db';
  static const _databaseVersion = 1;

  Database? _database;

  // 第三方日志服务与SentryFlutter结合使用
  final _logger = Logger('app.imscv.www');

  Future<Database> get database async {
    if (_database != null) return _database!;
    _database = await _initDatabase();
    return _database!;
  }

  // 初始化数据库
  Future<Database> _initDatabase() async {
    final dbPath = await getDatabasesPath();
    final path = join(dbPath, _databaseName);

    final db = await openDatabase(
      path,
      version: _databaseVersion,
      onCreate: _onCreate,
      onUpgrade: _onUpgrade,
    );
    return db;
  }

  // 创建表
  Future<void> _onCreate(Database db, int version) async {
    await db.execute('''
      CREATE TABLE IF NOT EXISTS logs (
         ${DbTables.id} INTEGER PRIMARY KEY AUTOINCREMENT,
        level TEXT NOT NULL,
        message TEXT NOT NULL,
        timestamp INTEGER NOT NULL,
        stack_trace TEXT,
        tag TEXT
      )
    ''');
  }

  // 数据库升级
  Future<void> _onUpgrade(Database db, int oldVersion, int newVersion) async {
    if (oldVersion < 1) {
      // 未来升级逻辑
    }
  }

  // 日志级别 - 详细
  Future<void> verbose({
    required String message,
    String? stackTrace,
    String? tag,
  }) {
    _logger.finest(message);
    return _insertLog(
      level: CacheLogLevel.verbose,
      message: message,
      stackTrace: stackTrace,
      tag: tag,
    );
  }

  // 日志级别 - 信息
  Future<bool> info(
    String message, {
    String? stackTrace,
    String? tag,
  }) {
    _logger.info(message);
    return _insertLog(
      level: CacheLogLevel.info,
      message: message,
      stackTrace: stackTrace,
      tag: tag,
    );
  }

  // 日志级别 - 调试
  Future<void> debug(
    String message, {
    String? stackTrace,
    String? tag,
  }) {
    _logger.fine(message);
    return _insertLog(
      level: CacheLogLevel.debug,
      message: message,
      stackTrace: stackTrace,
      tag: tag,
    );
  }

  // 日志级别 - 警告
  Future<void> warning(
    String message, {
    String? stackTrace,
    String? tag,
  }) {
    _logger.warning(message);
    return _insertLog(
      level: CacheLogLevel.warning,
      message: message,
      stackTrace: stackTrace,
      tag: tag,
    );
  }

  // 日志级别 - 错误
  Future<void> error(
    String message, {
    String? stackTrace,
    String? tag,
  }) {
    _logger.severe(message);
    return _insertLog(
      level: CacheLogLevel.error,
      message: message,
      stackTrace: stackTrace,
      tag: tag,
    );
  }

  // 日志级别 - 致命错误
  Future<void> fatal(
    String message, {
    String? stackTrace,
    String? tag,
  }) {
    _logger.shout(message);
    return _insertLog(
      level: CacheLogLevel.fatal,
      message: message,
      stackTrace: stackTrace,
      tag: tag,
    );
  }

  // 插入日志
  Future<bool> _insertLog({
    required CacheLogLevel level,
    required String message,
    String? stackTrace,
    String? tag,
  }) async {
    debugPrint(message);
    final db = await database;
    return db
        .insert(
            'logs',
            {
              'level': level.value,
              'message': message,
              'timestamp': DateTime.now().millisecondsSinceEpoch,
              'stack_trace': stackTrace,
              'tag': tag,
            },
            conflictAlgorithm: ConflictAlgorithm.replace)
        .then((value) => value > 0);
  }

  // 获取日志列表
  Future<List<LogCacheModel>> getLogs({
    String? level,
    String? tag,
    int? limit,
    DateTime? startDate,
    DateTime? endDate,
  }) async {
    try {
      final where = <String>[];
      final whereArgs = <dynamic>[];

      if (level != null) {
        where.add('level = ?');
        whereArgs.add(level);
      }

      if (tag != null) {
        where.add('tag = ?');
        whereArgs.add(tag);
      }

      if (startDate != null) {
        where.add('timestamp >= ?');
        whereArgs.add(startDate.millisecondsSinceEpoch);
      }

      if (endDate != null) {
        where.add('timestamp <= ?');
        whereArgs.add(endDate.millisecondsSinceEpoch);
      }
      final db = await database;
      return await db
          .query('logs',
              where: where.isNotEmpty ? where.join(' AND ') : null,
              whereArgs: whereArgs.isNotEmpty ? whereArgs : null,
              limit: limit,
              orderBy: 'timestamp DESC')
          .then((logs) {
        return logs.map((log) => LogCacheModel.fromMap(log)).toList();
      });
    } catch (e) {
      debugPrint('Failed to fetch logs: $e');
      return [];
    }
  }

  // 导出日志到文件
  Future<String> exportLogsAsCsv() async {
    final logs = await getLogs();
    final csv = StringBuffer();

    // Add CSV header
    csv.writeln('id,level,message,timestamp,stack_trace,tag');

    for (final log in logs) {
      final id = log.id ?? 0;
      final level = log.level;
      final timestamp = DateTime.fromMillisecondsSinceEpoch(
              log.timestamp.millisecondsSinceEpoch)
          .toIso8601String();

      // Safely escape CSV fields
      final message = _escapeCsvField(log.message);
      final stackTrace = _escapeCsvField(log.stackTrace ?? '');
      final tag = _escapeCsvField(log.tag ?? '');

      // Join row with commas
      csv.writeln('$id,$level,$message,$timestamp,$stackTrace,$tag');
    }

    return csv.toString();
  }

  // Helper method for escaping CSV fields
  String _escapeCsvField(String field) {
    if (field.contains('"') || field.contains(',') || field.contains('\n')) {
      return '"${field.replaceAll('"', '""')}"';
    }
    return field;
  }

  // 清空日志
  Future<void> clearAllLogs() async {
    final db = await database;
    await db.delete('logs');
  }

  // 删除超过7天的日志
  DateTime? _lastCleanupTime;

  Future<void> cleanOldLogs(int maxLogDays) async {
    try {
      // Check if cleanup was performed recently (within the last hour)
      final now = DateTime.now();
      if (_lastCleanupTime != null &&
          now.difference(_lastCleanupTime!).inHours < 1) {
        if (kDebugMode) {
          debugPrint('Skipping log cleanup - already performed recently');
        }
        return;
      }

      final db = await database;
      final threshold =
          now.subtract(Duration(days: maxLogDays)).millisecondsSinceEpoch;

      final deletedCount = await db.delete(
        'logs',
        where: 'timestamp < ?',
        whereArgs: [threshold],
      );

      _lastCleanupTime = now;

      if (kDebugMode && deletedCount > 0) {
        debugPrint('Cleaned $deletedCount old log entries');
      }
    } catch (e) {
      debugPrint('Error cleaning old logs: $e');
    }
  }

  // 重置数据库（测试用）
  Future<void> resetTestDatabase() async {
    // 使用测试专用的数据库路径
    final testDbPath = join(await getDatabasesPath(), _databaseName);
    // 删除现有数据库
    try {
      await deleteDatabase(testDbPath);
    } catch (e) {
      debugPrint('删除测试数据库失败: $e');
    }
    // 初始化新数据库
    final db = await openDatabase(testDbPath);
    await db.close();
  }
}
